/*
#
#  Copyright 2011 Matthew Jannace
#
#  This file is part of RoboCode BlackHoleAgent
#
#  RoboCode BlackHoleAgent is free software: you can redistribute it and/or
#  modify it under the terms of the GNU General Public License as
#  published by the Free Software Foundation, either version 3 of the
#  License, or (at your option) any later version.
#
#  RoboCode BlackHoleAgent is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#  General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with RoboCode BlackHoleAgent. If not, see
#  <http://www.gnu.org/licenses/>.
#
 */
package com.jannaceltd.TeamBlackHoleBeer.Utilities;

import com.jannaceltd.TeamBlackHoleBeer.BlackHole_Abstract;
import com.jannaceltd.TeamBlackHoleBeer.BlackHole_Interface;
import com.jannaceltd.TeamBlackHoleBeer.Modules.Debug.FileLog;
import robocode.BattleEndedEvent;
import robocode.BattleResults;
import robocode.DeathEvent;
import robocode.HitByBulletEvent;
import robocode.HitRobotEvent;
import robocode.HitWallEvent;
import robocode.RoundEndedEvent;
import robocode.WinEvent;

/**
 * Class that track damage statistics for an agent
 * @author Matthew Jannace <mjannace@gmail.com>
 * @version 1.0
 */
public class RobotStats implements BlackHole_Interface {

    private String FilePath = "";
    private String battleLogName = "BattleLOG.csv";
    private String roundLogName = "RoundLOG.csv";
    private BlackHole_Abstract Agent;
    private int Bullet_HitByTeammateCnt = 0;
    private double Bullet_HitByTeammateDamage = 0;
    private int Bullet_HitByEnemyCnt = 0;
    private double Bullet_HitByEnemyDamage = 0;
    private int HitTeammateCnt = 0;
    private double HitTeamateDamage = 0;
    private double HitEnCnt = 0;
    private double HitEnDamage = 0;
    private int HitWallCnt = 0;
    private double HitWallDamage = 0;
    private double startingEnergyLevel = 0;

    /**
     * Creates a new RobotStas object
     * @param Agent
     */
    public RobotStats(BlackHole_Abstract Agent, String filePath) {
        this.Agent = Agent;
        this.startingEnergyLevel = Agent.getEnergy();
        this.FilePath = filePath;
    }

    /**
     * Tracks Damages caused by Teammates
     * @param event
     */
    public void onHitByBullet(HitByBulletEvent event) {
        if (Agent.isTeammate(event.getName())) {
            Bullet_HitByTeammateCnt++;
            Bullet_HitByTeammateDamage += MathUtils.bulletDamage(event.getPower());
        } else {
            Bullet_HitByEnemyCnt++;
            Bullet_HitByEnemyDamage += MathUtils.bulletDamage(event.getPower());
        }
    }

    /**
     * Tracks Damages Agent causes to Teammates by ramming them
     * @param event
     */
    public void onHitRobot(HitRobotEvent event) {
        if (Agent.isTeammate(event.getName())) {
            HitTeammateCnt++;
            HitTeamateDamage += 0.6;
        } else {
            HitEnCnt++;
            HitEnDamage += 0.6;
        }
    }

    /**
     * Tracks Damages Agent causes to itself by ramming a wall
     * @param event
     */
    public void onHitWall(HitWallEvent event) {
        HitWallCnt++;
        HitWallDamage += MathUtils.WallDamage(Agent.getVelocity());
    }

    /**
     * Writes Statistics Gathered during a round and writes them to a file
     * @param event
     */
    public void onRoundEnded(RoundEndedEvent event) {
        //writeRoundData(event, false);
    }

    /**
     * Writes Statistics Gathered during a round and writes them to a file
     * @param event
     */
    public void onDeath(DeathEvent event) {
        writeRoundData(event, true);
    }

    public void onWin(WinEvent event) {
        writeRoundData(event, false);
    }

    /**
     * Writes Statistics Gathered during a Battle and writes them to a file
     * @param event
     */
    public void onBattleEnded(BattleEndedEvent event) {
        writeBattleData(event);
    }

    /**
     * Writes Statistics Gathered during a Battle and writes them to a file
     * @return Formated Battle Statistics string
     */
    @Override
    public String toString() {

        String result = "Damage Stats\n";






        if (Bullet_HitByTeammateCnt > 0) {
            result += "TeamMate Bullet Hit Count = " + Bullet_HitByTeammateCnt + "\n"
                    + "TeamMate Bullet Damage = " + Bullet_HitByTeammateDamage + "\n";






        }

        if (HitTeammateCnt > 0) {
            result += "TeamMate Collision Count = " + HitTeammateCnt + "\n"
                    + "TeamMate Collision Damage = " + HitTeamateDamage + "\n";






        }

        if (HitEnCnt > 0) {
            result += "Enemy Collision Count = " + HitEnCnt + "\n"
                    + "Enemy Collision Damage = " + HitEnDamage + "\n";






        }

        if (HitWallCnt > 0) {
            result += "Wall Collision Count = " + HitWallCnt + "\n"
                    + "Wall Collision Damage = " + HitWallDamage + "\n";






        }

        if ((Bullet_HitByTeammateDamage + HitTeamateDamage) > 0) {
            result += "Total Teammate Damage= " + (Bullet_HitByTeammateDamage + HitTeamateDamage) + "\n";






        }

        if ((Bullet_HitByTeammateDamage + HitTeamateDamage + HitEnDamage + HitWallDamage) > 0) {
            result += "OverAll Total Damage = " + (Bullet_HitByTeammateDamage + HitTeamateDamage + HitEnDamage + HitWallDamage) + "\n";






        }

        if (result.equalsIgnoreCase("Damage Stats\n")) {
            return "";






        } else {
            return result;






        }
    }

    private void writeRoundData(Object event, boolean died) {

        String headerStr = "";
        String statsStr = "";

        headerStr += "Robot Name,";
        statsStr += Agent.getName() + ",";

        headerStr += "Round Number,";
        statsStr += Agent.getRoundNum() + ",";

        headerStr += "Team Size,";
        statsStr += (Agent.getTeammates().length + 1) + ",";

        headerStr += "# TeamMates Left,";
        statsStr += (died ? 0 : Agent.teamates.size() + 1) + ",";

        headerStr += "Win Round,";
        statsStr += (!died && Agent.getEnergy() > 0 ? 1 : 0) + ",";

        headerStr += "Start Energy Level,";
        statsStr += startingEnergyLevel + ",";

        headerStr += "End Energy Level,";
        statsStr += Agent.getEnergy() + ",";

        headerStr += "Max # Turn in reached,";
        statsStr += Agent.getTime() + ",";

/////////////////////////////////////////////////////////////////////////

        headerStr += "--> Damage Done to Enemy By Agent -->,";
        statsStr += "-->,";

        headerStr += "# Agent Bullets Shot,";
        statsStr += Agent.gun.getFireCounter() + ",";

        headerStr += "# Agent Bullets Hit,";
        statsStr += Agent.gun.getHitCounter() + ",";

        headerStr += "Total Agent->Enemy Bullet Damage,";
        statsStr += Agent.gun.getEnemyDamage() + ",";

/////////////////////////////////////////////////////////////////////////

        headerStr += "--> Damage Done to Agent By Enemy -->,";
        statsStr += "-->,";

        headerStr += "# Enemy Bullets Hit Agent,";
        statsStr += Bullet_HitByEnemyCnt + ",";

        headerStr += "Total Enemy->Agent Bullets Damage,";
        statsStr += Bullet_HitByEnemyDamage + ",";

        headerStr += "Enemy Collision Count,";
        statsStr += HitEnCnt + ",";

        headerStr += "Enemy Collision Damage,";
        statsStr += HitEnDamage + ",";

/////////////////////////////////////////////////////////////////////////

        headerStr += "--> Damage Done to Agent By Team -->,";
        statsStr += "-->,";

        headerStr += "TeamMate Bullet Hit Count,";
        statsStr += Bullet_HitByTeammateCnt + ",";

        headerStr += "TeamMate Bullet Damage,";
        statsStr += Bullet_HitByTeammateDamage + ",";

        headerStr += "TeamMate Collision Count,";
        statsStr += HitTeammateCnt + ",";

        headerStr += "TeamMate Collision Damage,";
        statsStr += HitTeamateDamage + ",";

/////////////////////////////////////////////////////////////////////////

        headerStr += "--> Damage Done to Agent By Agent -->,";
        statsStr += "-->,";

        headerStr += "Wall Collision Count,";
        statsStr += HitWallCnt + ",";

        headerStr += "Wall Collision Damage,";
        statsStr += HitWallDamage + ",";

/////////////////////////////////////////////////////////////////////////

        headerStr += "--> Total Damage Done to Agent-->,";
        statsStr += "-->,";

        headerStr += "Total Teammate Damage,";
        statsStr += (Bullet_HitByTeammateDamage + HitTeamateDamage) + ",";

        headerStr += "OverAll Total Damage";
        statsStr += (Bullet_HitByEnemyDamage + Bullet_HitByTeammateDamage + HitTeamateDamage + HitEnDamage + HitWallDamage);

/////////////////////////////////////////////////////////////////////////

        FileLog log = new FileLog(Agent, roundLogName, FilePath + "/round");

        if (!log.FileExist) {
            log.writeln(headerStr);
        }
        log.writeln(statsStr);

        log.close();
    }

    private void writeBattleData(Object event) {
        BattleResults results = ((BattleEndedEvent) event).getResults();

        String headerStr = "";
        String statsStr = "";

        headerStr += "Robot Name,";
        statsStr += Agent.getName() + ",";

        headerStr += "Rank,";
        statsStr += results.getRank() + ",";

        headerStr += "Score,";
        statsStr += results.getScore() + ",";

        headerStr += "Bullet Damage,";
        statsStr += results.getBulletDamage() + ",";

        headerStr += "Bullet Damage Bonus,";
        statsStr += results.getBulletDamageBonus() + ",";

        headerStr += "Survival,";
        statsStr += results.getSurvival() + ",";

        headerStr += "Last Survivor Bonus,";
        statsStr += results.getLastSurvivorBonus() + ",";

        headerStr += "Ram Damage,";
        statsStr += results.getRamDamage() + ",";

        headerStr += "Ram Damage Bonus";
        statsStr += results.getRamDamageBonus();

        FileLog log = new FileLog(Agent, battleLogName, FilePath + "/battle");








        if (!log.FileExist) {
            log.writeln(headerStr);






        }
        log.writeln(statsStr);

        log.close();



    }
}
